/**
 * 事件观察者类；
 */
class EventObserverClass {
  // 当前实例
  // static instance

  constructor () {
    this.eventList = {}
    this.instance = null
  }

  /**
   * @function 静态方法；单例模式获取实例
   * @author eleven
   */
  static getInstance () {
    if (!this.instance) {
      this.instance = new EventObserverClass()
    }
    return this.instance
  }

  /**
   * @function 发布
   * @author eleven
   * @param {*} handleName 事件名
   * @param {*} data 传递的参数
   * @param {Booblean} isFinishAndDel 完成后是否删除
   */
  publish (handleName, data, isFinishAndDel = true) {
    // 如果不存在该订阅事件列表
    if (!this.eventList[handleName]) {
      return
    }
    const fnList = this.eventList[handleName]
    // 轮训执行所有存储的订阅事件，执行完之后删除
    fnList.forEach((fn, index) => {
      fn(data)
      isFinishAndDel && fnList.splice(index, 1)
      // 如果该订阅事件的列表为空，则删除
      !fnList.length && this.unSubscribe(handleName)
    })
    // console.table(this.eventList)
  }

  /**
   * @function 订阅
   * @author eleven
   * @param {*} handleName 事件名
   * @param {*} fn 监听事件
   */
  subscribe (handleName, fn) {
    if (!this.eventList[handleName]) {
      this.eventList[handleName] = []
    }

    const fnIndex = this.eventList[handleName].indexOf(fn)
    // 只订阅还未存储的事件
    if (fnIndex === -1) {
      this.eventList[handleName].push(fn)
    }
  }

  /**
   * @function 取消订阅
   * @author eleven
   * @param {*} handleName 事件名
   */
  unSubscribe (handleName, fn) {
    // 如果不存在该订阅事件
    if (!this.eventList[handleName]) {
      return
    }

    // 如果该订阅事件中，事件列表为空;或者没有传递需要删除的fn，则删除订阅事件
    if (this.eventList[handleName].length === 0 || !fn) {
      delete this.eventList[handleName]
      return
    }

    const fnIndex = this.eventList[handleName].indexOf(fn)
    // 如果存在当前要取消订阅的事件，则从事件列表中移除
    if (fnIndex > -1) {
      this.eventList[handleName].splice(fnIndex, 1)
    }
  }

  /**
   * @function 根据事件名，获取事件列表长度
   * @param {*} handleName 事件名
   */
  getEventListLengthByHanderName (handlerName) {
    return this.eventList[handlerName] && this.eventList[handlerName].length
  }
}

const eventObserver = EventObserverClass.getInstance()
export default eventObserver
